package com.fourhats.controller;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.fourhats.model.UploadedFile;
import com.fourhats.services.util.FileHelper;
import com.fourhats.services.util.FolderSize;
import com.fourhats.services.util.ImageInfo;

@Controller
@RequestMapping("/image")
public class UploadImageController {
	
	@Value("#{configProps}")
	private Properties properties;
	
	private final String SMALL_IMAGE_FOLDER = "small";
	private final String MEDIUM_IMAGE_FOLDER = "medium";
	private final String LARGE_IMAGE_FOLDER = "large";
	private final String ORIGINAL_IMAGE_FOLDER = "originals";
	
	/*TEMP FOLDER*/
	private final String SMALLPRODUCT_TEMPFOLDER = "small_products";
	private final String SMALLMARKET_TEMPFOLDER = "small_markets";
	private final String ORIGINAL_TEMP_FOLDER = "originals";
	
	/*************************************************************************
	 *								PRODUCT
	 ************************************************************************/
	@RequestMapping(value="/uploadProductImg", method=RequestMethod.POST)
	public @ResponseBody UploadedFile uploadProductImg(@RequestParam("file") MultipartFile file) throws Exception {
		String tempPath = properties.getProperty("folder.temp");
		List<ImageInfo> imagesInfo = new ArrayList<ImageInfo>();
		imagesInfo.add(new ImageInfo(SMALLPRODUCT_TEMPFOLDER, 275, 162));
		
		return uploadTempImage(file, tempPath, imagesInfo);
	}
	
	@RequestMapping(value="/productTemp", method=RequestMethod.GET)
	public void productTemp(HttpServletResponse response, String fileName, String type) {
		String tempPath = properties.getProperty("folder.temp");
		File directory = new File(tempPath, SMALLPRODUCT_TEMPFOLDER);
		handleImage(response, fileName, directory.getAbsolutePath());
	}
	
	@RequestMapping(value="/productThumb", method=RequestMethod.GET)
	public void productThumb(HttpServletResponse response, String fileName, String type) {
		if(fileName == null || fileName == "") { 
			fileName = "defaultProduct.jpg";
			type = "";
		}
		
		String productPath = properties.getProperty("folder.product");
		processImageThumb(fileName, productPath, type, response);
	}
	
	/*************************************************************************
	 *								MARKET
	 ************************************************************************/
	
	@RequestMapping(value="/uploadMarketImg", method=RequestMethod.POST)
	public @ResponseBody UploadedFile uploadMarketImg(@RequestParam("file") MultipartFile file) throws Exception{
		
		String tempPath = properties.getProperty("folder.temp");
		List<ImageInfo> imagesInfo = new ArrayList<ImageInfo>();
		imagesInfo.add(new ImageInfo(SMALLMARKET_TEMPFOLDER, 275, 162));
		
		return uploadTempImage(file, tempPath, imagesInfo);
	}
	
	@RequestMapping(value="/marketTemp", method=RequestMethod.GET)
	public void marketTemp(HttpServletResponse response, String fileName, String type){
		String tempPath = properties.getProperty("folder.temp");
		File directory = new File(tempPath, SMALLMARKET_TEMPFOLDER);
		handleImage(response, fileName, directory.getAbsolutePath());
	}
	
	@RequestMapping(value="/marketThumb", method=RequestMethod.GET)
	public void marketThumb(HttpServletResponse response, String fileName, String type) {
		if(fileName == null || fileName == "") { 
			fileName = "defaultMarket.jpg";
			type = "";
		}
		
		String marketPath = properties.getProperty("folder.market");
		processImageThumb(fileName, marketPath, type, response);
	}
	
	/*************************************************************************
	 *								POST
	 ************************************************************************/
	
	@RequestMapping(value="/postThumb", method=RequestMethod.GET)
	public void postThumb(HttpServletResponse response, String fileName) {
		if(fileName == null || fileName == "") { 
			fileName = "defaultPost.jpg";
		}
		
		String postPath = properties.getProperty("folder.post");
		processImageThumb(fileName, postPath, "", response);
	}
	
	
	@RequestMapping(value="/uploadCrop", method=RequestMethod.POST)
	public @ResponseBody UploadedFile uploadCrop(MultipartHttpServletRequest request, HttpServletResponse response) throws IOException{
		String tempPath = properties.getProperty("folder.temp");
		return FileHelper.getUploadedFile(request, tempPath);
	}
	
	@RequestMapping(value="/uploadAvatarCrop", method=RequestMethod.POST)
	public @ResponseBody UploadedFile uploadAvatarCrop(MultipartHttpServletRequest request, HttpServletResponse response) throws IOException{
		String tempPath = properties.getProperty("folder.avatar");
		return FileHelper.getUploadedFile(request, tempPath);
	}
	
	@RequestMapping(value="/uploadAvatar", method=RequestMethod.POST)
	public @ResponseBody UploadedFile uploadAvatar(@RequestParam("file") MultipartFile file) throws Exception{
		String avatarPath = properties.getProperty("folder.avatar");
		
		BufferedImage imageSrc = null;
		List<ImageInfo> imagesInfo = new ArrayList<ImageInfo>();
		try{
			imageSrc = ImageIO.read(file.getInputStream());
			imagesInfo.add(new ImageInfo(SMALL_IMAGE_FOLDER, 125, 100));
			imagesInfo.add(new ImageInfo(MEDIUM_IMAGE_FOLDER, 275, 191));
			imagesInfo.add(new ImageInfo(LARGE_IMAGE_FOLDER, imageSrc.getWidth(), imageSrc.getHeight()));
		} catch(Exception e){
			throw e;
		}finally{
			if(imageSrc != null){
				imageSrc.flush();
			}
		}
		
		return uploadTempImage(file, avatarPath, imagesInfo);
	}
	
	@RequestMapping(value="/temp", method=RequestMethod.GET)
	public void temp(HttpServletResponse response, String fileName){
		String tempPath = properties.getProperty("folder.temp");
		handleImage(response, fileName, tempPath);
	}
	
	@RequestMapping(value="/avatarThumb", method=RequestMethod.GET)
	public void avatarThumb(HttpServletResponse response, String fileName, String type){
		if(fileName == null || fileName == "") { 
			fileName = "defaultAvatar.jpg";
			type = "";
		}
		
		String avatarPath = properties.getProperty("folder.avatar");
		processImageThumb(fileName, avatarPath, type, response);
	}
	
	//TODO: Provisorio hasta solucionar el problema del crop.
	@RequestMapping(value="/uploadTempAvatar", method=RequestMethod.POST)
	public @ResponseBody UploadedFile uploadTempAvatar(@RequestParam("file") MultipartFile file) throws Exception{
		String tempPath = properties.getProperty("folder.temp");
		return uploadTempImage(file, tempPath, new ArrayList<ImageInfo>());
	}
	
	private void handleImage(HttpServletResponse response, String fileName, String imagePath) {
		response.setContentType("image/jpeg");
		OutputStream output  = null;
		FileInputStream input = null;
		File file = new File(imagePath, fileName);
		try {
			output = response.getOutputStream();
			input = new FileInputStream(file);
			byte[] buffer = new byte[(int) file.length()];
			input.read(buffer);
			response.setContentLength(buffer.length);
			output.write(buffer);
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			try {
				input.close();
				output.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	private UploadedFile uploadTempImage(MultipartFile file, String tempPath, List<ImageInfo> imagesInfo)
			throws IOException, Exception, FileNotFoundException {
		
		String generatedFileName = FileHelper.getUniqueImageName(file.getOriginalFilename());
		
		String extension = FilenameUtils.getExtension(generatedFileName);
		String newFileName = generatedFileName.replace("." + extension, ".jpg");
		
		String originalImgPath = FileHelper.getFullPath(tempPath, ORIGINAL_TEMP_FOLDER, generatedFileName);
		String convertedImgPath = FileHelper.getFullPath(tempPath, ORIGINAL_TEMP_FOLDER, newFileName);
		
		//copia la imagen original en la carpeta temp.
		FileCopyUtils.copy(file.getBytes(), new FileOutputStream(originalImgPath));
		
		
		boolean isJpg = extension.equals("jpeg") || extension.equals("jpg");
		if(!isJpg){
			//convierte la imagen a jpg.
			FileHelper.convertToJPG(originalImgPath, convertedImgPath);
		}
		
		//comprimir la nueva imagen jpg.
		byte[] compressedImageBytes = FileHelper.compress(isJpg ? originalImgPath : convertedImgPath, 0.2f);
		
		FileHelper.generateImages2(compressedImageBytes, tempPath, newFileName, imagesInfo);
		FileCopyUtils.copy(compressedImageBytes, new FileOutputStream(new File(tempPath, newFileName).getAbsolutePath()));
		
		return new UploadedFile(newFileName);
	}
	
	private void processImageThumb(String fileName, String sourcePath, String size, HttpServletResponse response) {
		FolderSize folderSize;
		try {
			folderSize = FolderSize.valueOf(size);
		} catch (IllegalArgumentException e) {
			folderSize = FolderSize.none;
		}
		
		String child;
		switch (folderSize) {
			case small: child = SMALL_IMAGE_FOLDER;
				break;
			case medium: child = MEDIUM_IMAGE_FOLDER;
				break;
			case large: child = LARGE_IMAGE_FOLDER;
				break;
			case originals : child = ORIGINAL_IMAGE_FOLDER;
				break;
			default:
				child = "";
		}
		
		File directory = new File(sourcePath, child);
		handleImage(response, fileName, directory.getAbsolutePath());
	}
}
